<?php
/**
 * MySQLi 实现伪 pdo_mysql  
 *
 * @filesource _mysqli.class.php
 * @package peck 
 * @subpackage _db 
 * @version $id: 0.3, utf8, Mon Jan 11 22:29:47 CST 2010
 * @author LD King <kldscs[at]gmail.com>
 * @copyright Copyleft (D.) 2007 - 2010 MiFunny China Inc.
 * @link http://mifunny.info/
 * @example 
 *   
 */
include_once '_sql_prepare.class.php';

class _mysqli{
	/**
	 * @var int $query_count 本次连接所执行的SQL语句数目
	 */
	public $query_count = 0;
    private $mysqli = null;

    /**
     * 初始化 MySQLi
     *
     * @param array $policy
     */
    public function __construct($policy){
        if( empty($policy) ){
            throw new LogicException('('.__METHOD__.')'.
                'Error: empty database policy array !');
        }else{
            $this->mysqli = new mysqli($policy['host'], $policy['username'], $policy['password'], $policy['dbname'], $policy['unix_socket']);
            if($this->mysqli->connect_error) {
                throw new RuntimeException('('.__METHOD__.')'.
                    'MySQL Connect Error: #'.$this->mysqli->connect_errno . ', '.$this->mysqli->connect_error);
            }else{
                if( !empty($policy['charset']) ){
                    $charset = 'SET NAMES '.$policy['charset'];
                    if( !empty($policy['collate']) ){
                        $charset .= ' COLLATE '.$policy['collate'];
                    }
                    $this->exec( $charset );
                }//END set charset
            }
        }
    }//END func __construct

    public function __destruct(){
        if( $this->mysqli instanceof mysqli ){
            $this->mysqli->close();
        }
    }

    /**
     * 错误代码
     *
     * @return mixed
     */
    public function errorCode(){
        return mysqli_connect_errno();
    }

    /** 
     * 错误性息
     *
     * @return array
     */
    public function errorInfo(){
        return mysqli_connect_error();
    }

    /**
     * 执行SQL语句
     *
     * @param string $statement
     *
     * @return int
     */
    public function exec($statement){
        if( $this->mysqli->query($statement) ){
            ++ $this->query_count;
            return TRUE;
        }else{
            throw new RuntimeException('('.__METHOD__.')'.
                'SQL execute Error: #'.$this->errorCode().', '.$this->errorInfo() );
            return FALSE;
        }
    }

    /**
     * 执行SQL语句,返回结果集
     *
     * @param string $statement
     *
     * @return MagicStatement
     */
    public function query($statement){
        if( $stmt = $this->mysqli->query($statement) ){
            ++ $this->query_count;
            return new _mysqliStatement($this->mysqli, $stmt); 
        }else{
            throw new RuntimeException('('.__METHOD__.')'.
                'SQL execute Error: #'.$this->errorCode().', '.$this->errorInfo() );
            return FALSE;
        }
    }

    /**
     * 预执行SQL语句
     *
     * @param string $statement
     *
     * @return _mysqliStatement
     */
    public function prepare($statement){
        return new _mysqliStatement($this->mysqli, null, $statement);
    }

    /**
     * 得到最近一次insert的ID
     *
     * @return string
     */
    public function lastInsertId(){
        return $this->mysqli->insert_id;
    }
    
    /**
     * 去除SQL语句中不合法的字符
     *
     * @param string $string
     *
     * @return string
     */
    public function quote($string){
        return '\''.$this->mysqli->real_escape_string($string).'\'';
    }

    /**
     * 开始事务
     */
    public function beginTransaction(){
        $this->mysqli->autocommit(FALSE);
    }

    /**
     * 提交事务
     */
    public function commit(){
        $this->mysqli->commit();
    }

    /**
     * 回滚事务
     */
    public function rollBack(){
        $this->mysqli->rollback();
    }

}//END interface MagicDB

/**
 * MagicDB 结果集
 */
class _mysqliStatement extends SQL_Prepare{

    //首先实现两个抽象方法
    protected function escape($string){
        return '\''.$this->db->real_escape_string($string).'\'';
    }
    protected function query($sql){
        if( $this->stmt = $this->db->query($sql) ){
            return TRUE;    
        }else return FALSE;
    }
    public function __destruct(){
        parent::__destruct();
        $this->nextRowset();
    }

    /**
     * 获得单行结果
     *
     * @return mixed
     */
    public function fetch(){
        if( $this->stmt instanceof MySQLi_Result ){
            $row = $this->stmt->fetch_assoc();
        	if( empty($row) ){
    		    return FALSE;
    	    }else return $row;
        }else{
            throw new RuntimeException('('.__METHOD__.')Error: Empty SQL Statement.');
            return FALSE;
        }
    }

    /**
     * 获取所有结果
     *
     * @return array
     */
    public function fetchAll(){
        if( $this->stmt instanceof MySQLi_Result ){
            $rows = array();
            while( $row = $this->stmt->fetch_assoc() ) {
                $rows[] = $row;
            }
    	    return $rows; 
        }else{
            throw new RuntimeException('('.__METHOD__.')Error: Empty SQL Statement.');
            return FALSE;
        }
    }
    
    /**
     * 结果计数
     *
     * @return int
     */
    public function rowCount(){
        if( $this->stmt instanceof MySQLi_Result ){
            return $this->stmt->num_rows;
        }else return 0;
    }

    /**
     * 下一个结果集
     *
     * @return bool
     */
    public function nextRowset(){
        $this->closeCursor();
        return $this->db->next_result();
    }

    /**
     * 关闭结果集
     *
     * @return bool
     */
    public function closeCursor(){
        if( $this->stmt instanceof MySQLi_Result ){
            $this->stmt->free();
            $this->stmt = NULL;
        }
        return TRUE;
    }
}//END class _mysqliStatement
?>
